#include <pthread.h>
#include <queue>
#include <vector>

#ifndef _EXECUTOR_H
#define _EXECUTOR_H

#define JOB_DEFAULT_PRIORITY 0

class Job {
   public:
       virtual Job* execute() = 0;
       virtual int priority();
};

class Runnable {
    public:
        virtual void run() = 0;
};

class Thread {
    public:
	Thread(Runnable* runnable = NULL);
	~Thread();
        void start();
	void join();
	virtual void run();
    private:
        Runnable* runnable;
	pthread_t id;
	static void* srun(void*);
};

class Lock {
    private:
	pthread_mutex_t mutex;
	pthread_cond_t cond;
    public:
	Lock();
	~Lock();
        void lock();
	void unlock();
	bool tryLock();
	void wait();
	void wait(long millis);
	void notify();
	void notifyAll();
};

class Executor : Runnable {
    public:
	Executor(int pool_size);
	void startAll();
        void schedule(Job* job);
	~Executor();
	void run();
    private:
        volatile int pool_size;
	volatile int pool_limit;
	volatile bool running;
	Thread** threads;
        Lock* lock;
	std::queue<Job*> job_queue;

	Job* next();
	bool inc();
	bool needInc();
};

#endif
